整理自《第一行代码》,原文过于啰嗦不便查阅,故摘抄整理之。理解肤浅,有错见谅。

插图均来自material.io,侵删。

工具栏 Toolbar

如何使用Toolbar?

  1. 修改主题(在res/values/style.xml中)为Theme.AppCompact.NoActionBar(深色)或Theme.AppCompact.Light.NoActionBar(浅色),目的是隐藏默认的ActionBar

  2. 设置颜色,即ColorPrimary等属性(在res/values/style.xml中)

  3. 在布局中引入Toolbar(包为androidx.appcompat.widget.Toolbar

  4. 布局应该重设命名空间为xmlns:app

  5. Activity中调用setSupportActionBar(toolbar)

使用app命名空间,而不是android,是为了兼容老版本,防止和旧控件冲突

如何配置Toolbar显示的内容?

  1. 文字:修改AndroidManifest.xml,当中<application>标签下,可以设置对应Activity的的标题栏文字

  2. 增加按钮

    1. 新建Menu Resource,添加<item>和对应的action按钮,android:idandroid:iconandroid:title分别设定id、图标和文字

    2. 设置app:showAsAction指定按钮的显示位置,alwaysifRoomnever分别对应「永远显示」、「无空间则进菜单」和「永远在菜单中」

    3. 设置按钮的事件:override onOptionItemSelected(item: Menu Item)

更高级的Toolbar——可折叠工具栏CollapsingToolbarLayout

抽屉布局 DrawerLayout

  1. 直接使用DrawerLayout,其下第一个子控件为主界面,第二个子控件为抽屉中的内容(layout_gravity最好设为start

  2. Toolbar最左侧添加菜单按钮「Home按钮」:在Activity中,设置

    supportActionBar?.let {
        it.setDisplayHomeAsUpEnabled(true) // 启用菜单按钮
        it.setHomeAsUpIndicator(R.drawable.ic_menu) // 图标
    }
    

    然后在重写的onOptionsItemSelected中,当菜单按钮被按下时唤出抽屉

    // ...
    when (item.itemId) {
        // home按钮的id永远是home
        android.R.id.home -> drawerLayout.openDrawer(GravityCompat.START)
    }
    // ...
    

导航视图 NavigationView

导航视图适合与抽屉布局一起使用。

包括两个部分:headerLayoutmenu。分别需要定义对应部分的布局。menu还需要有个xml文件定义菜单中的具体项目。

设置完成所需的xml后,将NavigationView添加到DrawerLayout中。

要处理对应的点击事件,只要调用NavigationView对象的setNavigationItemSelectedListener进行设置,比如

navView.setNavigationItemSelectedListener {
    drawerLayout.closeDrawers()
    true // 表示事件已经被处理
}

悬浮按钮 FloatingActionButton

相当简单,在布局中加入<com.google.android.material.floatingactionbutton.FloatingActionButton>,设置对应的图标和其他属性。设置app:elevation可以调整z轴上的「悬浮高度」。

默认颜色为colorAccent

点击事件和Button没有区别。setOnClickListener,相当简单。

「快餐店」 SnackBar

SnackBar一定程度上可以替代「吐司」Toast。相比Toast,用户不仅仅是被动接受通知,而是可以给出一定反馈。

Example of snackbar on a mobile screen

用法类似Toast,比如

Snackbar.make(view, "Can't send photo", Snakebar.LENGTH_SHORT)
    .setAction("Retry") {
        // retry
    }.show()
}

协调布局 CoordinatorLayout

增强版的FrameLayout,具有一定Material Design相关的能力。比如Snakebar弹出的时候不会覆盖住「悬浮按钮」,而是会将悬浮按钮「挤」上去。

卡片视图 MaterialCardView

原先的卡片加了点阴影。略。

应用栏布局 AppBarLayout

使用协调布局时,Toolbar会被主体部分遮盖。因此引入应用栏布局。使用时将Toolbar包裹到AppBarLayout当中即可保证Toolbar不被遮挡。而且可以顺带通过调整app:layout_scrollFlags来实现向上滚动自动隐藏Toolbar的功能。

下拉刷新布局 SwipeRefreshLayout

Material Design风格的下拉刷新。使用的时候可以把RecyclerView包裹到下拉刷新布局中。

假设SwipeRefreshLayout的id为swipeRefresh,那么用例如下

swipeRefresh.setColorSchemeResources(R.color.colorPrimary)
swipeRefresh.setOnRefreshListener {
    // 刷新逻辑
    myRefresh(adapter)
}
private fun myRefresh(adapter: XXXAdapter) {
    thread {
        // Thread.sleep(2000)
        runOnUiThread {
            // ...
            adapter.notifyDataSetChanged()
            swipeRefresh.isRefreshing = false;
        }
    }
}

下拉自动开始刷新(显示刷新进度条,并用thread函数开新线程执行刷新逻辑),刷新完成后,用runOnUiThread回到界面线程并停止刷新(隐藏刷新进度条)。

其他种种部件

material.io应有尽有。